﻿using STHPMS1.BLL.B_Core;
using STHPMS1.Common.C_Entity.Stmpms1;
using STHPMS1.ICore.I_BLL.Bus;
using STHPMS1.ICore.I_Entity.Info;
using STHPMS1.ICore.I_Entity.Stmpms1;
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq.Expressions;
using STHPMS1.ICore.I_DAL;
using System.Text;
using System.Linq;
using STHPMS1.ICore.I_Serv;
using STHPMS1.BLL.B_Serv;

namespace STHPMS1.BLL.B_Bus
{
    public class Dn_Divi_ResultBus : BllBase, IDn_Divi_ResultBill
    {
        public void Save<T>(T entity)
            where T : class ,IDn_Divi_Result
        {
            if (this.Scene.Dal.Sthpms1.Update(entity) == 0)
            {
                this.Scene.Dal.Sthpms1.Insert(entity);
            }
        }

        public void Remove(IDn_Divi_Result entity)
        {
            this.Scene.Dal.Sthpms1.Delete(entity);
        }

        public void RemoveAll(IDn_Divi_Result entity)
        {
             ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
             using (IDbTransaction dbTrans = dao.BeginTransaction())
             {
                 dao.Delete<IDn_Divi_Result>(p => p.Mainsegid == entity.Mainsegid);
                 dao.Delete<IB_Invntory_Unit>(p => p.Segid == entity.Mainsegid);
                 dbTrans.Commit();
             }
        }

        public IDn_Divi_Result GetSingle(string MAINSEGID)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            return dao.Single<Dn_Divi_Result>(p => p.Mainsegid == MAINSEGID);
        }
        

        public void SaveAll<T1,T2>(T1[] result, T2[] ius)
            where T2:IB_Invntory_Unit
            where T1:IDn_Divi_Result
        {
            ISthpms1Dao dao=null;
            try
            {

                dao = this.Scene.Dal.Sthpms1;
                dao.OpenDbConnection();
                using (IDbTransaction dbTrans = dao.BeginTransaction())
                {
                    
                    dao.InsertAll(result);
                    dao.InsertAll(ius);
                    dbTrans.Commit();
                   
                }
            }
            catch (Exception ex)
            {
                
                throw;
            }
           finally
            {
                dao.CloseConnection();
            }
        }



        public int GetLastYear(string rdwayid, string mainsegid)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetLastYear(rdwayid, mainsegid);
        }


        public double GetRoadLenght(string rdwayid, string mainsegid)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetRoadLenght(rdwayid, mainsegid);
        }
        public double GetRoadAera(string rdwayid, string mainsegid)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetRoadAera(rdwayid, mainsegid);
        }


        public IEnumerable<T> GetNewSegment<T>(string rdwaryId, string m_w, IPagingInfo info) where T : class, IDn_Divi_Result
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetNewSegment<T>(rdwaryId,m_w, info);
        }


        public void Clear(string rdid, string gf_zb)
        {
            this.Scene.Dal.Sthpms1.Dn_Divi_Result.Clear(rdid, gf_zb);
        }

        public void ClearOther(string rdid, string gf_zb)
        {
            this.Scene.Dal.Sthpms1.Dn_Divi_Result.ClearOther(rdid, gf_zb);
        }

        public IEnumerable<T> GetMainNeedWay<T>(string rdwaryId) where T : class, IDn_Divi_Result
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetMainNeedWay<T>(rdwaryId);
        }


        public IEnumerable<T> GetNewRoad<T>(string rdwaryId, string dir, IPagingInfo info) where T : class, IDn_Divi_Result
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetNewRoad<T>(rdwaryId, dir, info);
        }


        public void ClearOtherChart(string rdid, string dir)
        {
            this.Scene.Dal.Sthpms1.Dn_Divi_Result.ClearOtherChart(rdid, dir);
        }


        public DataTable GetRoadAvgZB(string rdid, string dir)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetRoadAvgZB(rdid, dir);
        }

        public void Update(IDn_Divi_Result[] diviList)
        {
            this.Scene.Dal.Sthpms1.Dn_Divi_Result.Update(diviList);
        }

        public IEnumerable<T> GetResulst<T>(IB_Roadnet roadnet) where T : class, IDn_Divi_Result
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetResulst<T>(roadnet);
        }

        public DataRow GetTe_Data(IDn_Divi_Result r)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetTe_Data(r);
        }

        /// <summary>
        /// 中修
        /// </summary>
        /// <param name="r"></param>
        /// <param name="y"></param>
        /// <param name="result"></param>
        /// <param name="modelPci"></param>
        /// <returns></returns>
        public double GetThick_Mid(IDn_Divi_Planning r, int y, IDn_Divi_Result result, ref string modelPci)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            B_Invntory ib_invntory = this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(r.Mainsegid) as B_Invntory;
            B_Pmstc b_pmstcinfo = dao.Single<B_Pmstc>(p => p.Rdwayid == ib_invntory.Rdwayid && p.Direction_Dictid == ib_invntory.Direction_Dictid && p.Beginmp <= ib_invntory.Beginmp && p.Endmp >= ib_invntory.Endmp);
            B_Layer b_layer1 = dao.Single<B_Layer>(p => p.Struid == b_pmstcinfo.Struid && p.Layer_Dictid == (int)Common.C_Enum.LayerEnum.L50);  //下面层
            double thick = 0;//面层厚度
            //查询上面层和中面层厚度
            DataTable dt = this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetThick_Up_Midlle(r.Project_Id);
            thick = Convert.ToDouble(dt.Rows[0]["UP_THICK"]) + Convert.ToDouble(dt.Rows[0]["MID_THICK"])+ Convert.ToDouble( b_layer1.Thick);//上+中+下

            //获取模型
            Dm_Modelgroup model = this.Scene.Bll.Dn_Divi_Result.GetModel<Dm_Modelgroup>(Convert.ToInt32(ib_invntory.Pvmttype_Dictid), Convert.ToInt32(ib_invntory.Basictype_Dictid), Convert.ToInt32(r.Segid_Main), "", thick) as Dm_Modelgroup;
            modelPci = model.Modelgroup_Id;
            //获取预测PCI
            return ModelCalculateService.CreateServiceByModel(model).CalculateY(GetEaslByModel(result, y));
        }

        /// <summary>
        /// 大修
        /// </summary>
        /// <param name="r"></param>
        /// <param name="y"></param>
        /// <param name="result"></param>
        /// <param name="modelPci"></param>
        /// <returns></returns>
        public double GetThick_Max(IDn_Divi_Planning r, int y, IDn_Divi_Result result, ref string modelPci)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            B_Invntory ib_invntory = this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(r.Mainsegid) as B_Invntory;
            B_Pmstc b_pmstcinfo = dao.Single<B_Pmstc>(p => p.Rdwayid == ib_invntory.Rdwayid && p.Direction_Dictid == ib_invntory.Direction_Dictid && p.Beginmp <= ib_invntory.Beginmp && p.Endmp >= ib_invntory.Endmp);
          
            double thick = 0;//面层厚度
            //查询上面层和中面层厚度和下面层
            DataTable dt = this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetThick_Up_Midlle_Down(r.Project_Id);
            if (dt.Rows.Count == 0) throw new Exception("没有找到对应的层数据");
            thick = Convert.ToDouble(dt.Rows[0]["UP_THICK"]) + Convert.ToDouble(dt.Rows[0]["MID_THICK"]) + Convert.ToDouble(dt.Rows[0]["DOWN_THICK"]);//上+中+下
            //如果大修表的厚度数据为0，则使用原始面层厚度
            if(thick==0)
                thick = Convert.ToDouble( b_pmstcinfo.Thick_S);

            //获取模型
            Dm_Modelgroup model = this.Scene.Bll.Dn_Divi_Result.GetModel<Dm_Modelgroup>(Convert.ToInt32(ib_invntory.Pvmttype_Dictid), Convert.ToInt32(ib_invntory.Basictype_Dictid), Convert.ToInt32(r.Segid_Main), "", thick) as Dm_Modelgroup;
            modelPci = model.Modelgroup_Id;
            //获取预测PCI
            return ModelCalculateService.CreateServiceByModel(model).CalculateY(GetEaslByModel(result, y));

            //return ModelCalculateService.CreateServiceByModel(model).CalculateY(0.67);
        }


        public double GetThick_S(string rdid, int dir, double start, double end)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetThick_S(rdid, dir, start, end);
        }

        #region 获取模型方法
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_dictid">面层类型</param>
        /// <param name="b_dictid">基层类型</param>
        /// <param name="m_dictid">养护类型</param>
        /// <param name="yftype">预防措施</param>
        /// <param name="thick">面层厚度</param>
        /// <returns></returns>
        public IDm_Modelgroup GetModel<T>(int p_dictid, int b_dictid, int m_dictid, string yftype, double thick) where T : class ,IDm_Modelgroup
        {  
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            if (yftype != "") //预防性措施
            {
                return dao.Single<T>(p => p.Pvmttype_Dictid == p_dictid && p.Basictype_Dictid == b_dictid && p.Modeltype_Dictid == m_dictid && p.Comment==yftype
                    && (thick>= p.Thick_Min && thick<= p.Thick_Max));
            }
            else
            {
                return dao.Single<T>(p => p.Pvmttype_Dictid == p_dictid && p.Basictype_Dictid == b_dictid && p.Modeltype_Dictid == m_dictid 
                   && (thick >= p.Thick_Min && thick <= p.Thick_Max));
            }
        }
        #endregion

        //获取预防性养护措施
        public string GetMeas_ini(string anniname, int year)
        {
            return this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetMeas_ini(anniname,year);
        }



        #region 模型处理

        //预测PCI
        public double GetPciByModel(IDn_Divi_Result result, int year)
        {
            IModelCalculateService serv = GetModelServ(result);
            return serv.CalculateY(GetEaslByModel(result, year));
        }

        #region 模型组和累计当量轴载
        private List<Dm_Esalage> _esalageList;
        private double GetEaslByModel(IDn_Divi_Result result, int year)
        {
            if (result == null) throw new Exception("决策路段信息不能为空!");
            int age = year - result.BeginDate.Value.Year;
            if (age < 0) throw new Exception("指定年份必段大于通车年份-" + year);
            double? esal = null;
            _esalageList = GetEsalageList(result.Segid) as List<Dm_Esalage>; //该路段不同路龄的累计当量轴载
            Dm_Esalage dm_esalage = _esalageList.FirstOrDefault(p => p.Perfyear == age);
            if (dm_esalage != null)
                esal = dm_esalage.Easl;
            if (esal == null) throw new Exception("该基础路段的路龄对应的累计轴载还没有计算-" + result.Segid + ":" + age);
            return (double)esal;
        }

        /// <summary>
        /// 累计当量轴载
        /// </summary>
        /// <param name="segId"></param>
        /// <returns></returns>
        private IEnumerable<Dm_Esalage> GetEsalageList(string segId)
        {
            if(Common.C_Utils.MyCacheTools.IsCacheExist("esal_"+segId))
            {
                return Common.C_Utils.MyCacheTools.GetCache("esal_" + segId) as IEnumerable<Dm_Esalage>;
            }
            else
            {
                IEnumerable<Dm_Esalage> temp = this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetEsalage<Dm_Esalage>(segId);
                Common.C_Utils.MyCacheTools.SetCache("esal_" + segId, temp, 24);
                return temp;
            }
        }

        /// <summary>
        /// 返回模型组
        /// </summary>
        /// <param name="groupId"></param>
        /// <returns></returns>
        private Dm_Modelgroup GetModelGroup(string groupId)
        {
            if (Common.C_Utils.MyCacheTools.IsCacheExist("model_" + groupId))
            {
                return Common.C_Utils.MyCacheTools.GetCache("model_" + groupId) as Dm_Modelgroup;
            }
            else
            {
                Dm_Modelgroup temp = this.Scene.Dal.Sthpms1.Dn_Divi_Result.GetModelGroup<Dm_Modelgroup>(groupId);
                Common.C_Utils.MyCacheTools.SetCache("model_" + groupId, temp, 24);
                return temp;
            }
        }

        private IModelCalculateService GetModelServ(IDn_Divi_Result result)
        {
            IDm_Modelgroup model = GetModelGroup(result.ModelGroup_PCI);//返回模型组       
            if (model == null) throw new Exception("模型信息不存在-" + result.ModelGroup_PCI);
            return ModelCalculateService.CreateServiceByModel(model);
        }

        #endregion

        #endregion
    }
}
